/**
 * 前端js库: IMU 1.0
 * Copyright(c) 2013 IMU-JS
 * iduosi@gmail.com
 * imu.com
 */

/**
 * @class Function
 * @content 补充 Function 内置对象
 */
Ext.apply(Function.prototype, {
    /**
	 * @content 创建回调，回调方法的上下文为全局window对象
     * @return {Function} The new function
	 */
    createCallback: function (/*args...*/) {
        // make args available, in function below
        var args = arguments;
        var method = this;
        return function() {
            return method.apply(window, args);
        };
    },
    /**
	 * @content 创建代理函数，函数上下文为指定的对象
     * @param {Object} obj 指定的上下文对象
     * @param {Array} args 方法执行的参数
     * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
     *                                             if a number the args are inserted at the specified position
     * @return {Function} The new function
     */
    createDelegate: function (obj, args, appendArgs) {
        var method = this;
        return function () {
            var callArgs = args || arguments;
            if(appendArgs === true){
                callArgs = Array.prototype.slice.call(arguments, 0);
                callArgs = callArgs.concat(args);
            }
			else if (typeof appendArgs == "number") {
                callArgs = Array.prototype.slice.call(arguments, 0);
                var applyArgs = [appendArgs, 0].concat(args);
                Array.prototype.splice.apply(callArgs, applyArgs);
            }
            return method.apply(obj || window, callArgs);
        };
    },

    /**
	 * @content 在指定的毫秒数之后调用函数，同时可以指定特定的作用域。
     * @param {Number} millis The number of milliseconds for the setTimeout call (if 0 the function is executed immediately)
     * @param {Object} obj (optional) The object for which the scope is set
     * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
     * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
     *                                             if a number the args are inserted at the specified position
     * @return {Number} The timeout id that can be used with clearTimeout
     */
    defer: function (millis, obj, args, appendArgs) {
        var fn = this.createDelegate(obj, args, appendArgs);
        if(millis){
            return setTimeout(fn, millis);
        }
        fn();
        return 0;
    },
    
    /**
	 * @content 使用原始的函数和传递进来的函数来创建一个组合的函数调用顺序，最终执行的函数返回原始函数的结果。使用原始函数的参数来调用传递进来的函数。 
     * @param {Function} fcn The function to sequence
     * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
     * @return {Function} The new function
     */
    createSequence: function (fcn, scope) {
        if (typeof fcn != "function") {
            return this;
        }
        var method = this;
        return function() {
            var retval = method.apply(this || window, arguments);
            fcn.apply(scope || this || window, arguments);
            return retval;
        };
    },

    /**
	 * @content 创建一个拦截函数。传入的函数在原始的函数之前执行。如果传入的函数返回false，就不执行原始的函数。最终函数返回原始函数的执行结果。传递进来的函数使用原始函数的参数来调用。 
     * @param {Function} fcn The function to call before the original
     * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
     * @return {Function} The new function
     */
    createInterceptor: function (fcn, scope) {
        if (typeof fcn != "function") {
            return this;
        }
        var method = this;
        return function () {
            fcn.target = this;
            fcn.method = method;
            if (fcn.apply(scope || this || window, arguments) === false) {
                return;
            }
            return method.apply(this || window, arguments);
        };
    }
});